/*
 * CCVisu is a tool for visual graph clustering
 * and general force-directed graph layout.
 * This file is part of CCVisu.
 *
 * Copyright (C) 2005-2011  Dirk Beyer
 *
 * CCVisu is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * CCVisu is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with CCVisu; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * Please find the GNU Lesser General Public License in file
 * license_lgpl.txt or http://www.gnu.org/licenses/lgpl.txt
 *
 * Dirk Beyer    (firstname.lastname@uni-passau.de)
 * University of Passau, Bavaria, Germany
 */
package org.sosy_lab.ccvisu.ui.controlpanel;

import java.awt.BorderLayout;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.SpinnerNumberModel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import org.sosy_lab.ccvisu.CCVisuOptions;
import org.sosy_lab.ccvisu.measuring.calldep.DependencyCalculator;
import org.sosy_lab.ccvisu.measuring.calldep.DependencyOptions;
import org.sosy_lab.ccvisu.measuring.calldep.DistanceVertexContainer;
import org.sosy_lab.ccvisu.measuring.calldep.OutdegreeVertexContainer;
import org.sosy_lab.ccvisu.measuring.calldep.colors.ColorProvider;
import org.sosy_lab.ccvisu.measuring.calldep.colors.ColorProvider.ColorOptions;
import org.sosy_lab.ccvisu.ui.helper.ClassCellRenderer;
import org.sosy_lab.common.LogManager;
import org.sosy_lab.common.configuration.Configuration;
import org.sosy_lab.common.configuration.InvalidConfigurationException;
import org.sosy_lab.util.interfaces.WorkerManager;

public class ToolPanelMeasurer extends ControlPanel {
  private static final long serialVersionUID = -7114139321544094720L;

  private CCVisuOptions      options;
  private WorkerManager      workerManager;

  private JButton            startAnalysisButton = new JButton("Run dependency analyzer");
  private JCheckBox          tooltipCheckbox     = new JCheckBox();

  // generic since Java 7; we require Java 6; see svn r825 for comparison
  @SuppressWarnings("rawtypes")
  private JComboBox          algorithmComboBox   = new JComboBox();

  @SuppressWarnings("rawtypes")
  private JComboBox          coloringComboBox    = new JComboBox();

  private SpinnerNumberModel labelSpinnerModel;

  private DependencyOptions depOptions;

  private final LogManager logger;

  public ToolPanelMeasurer(CCVisuOptions options, WorkerManager worker,
      Configuration config, LogManager logger)
          throws InvalidConfigurationException {

    this.options = options;
    this.workerManager = worker;
    this.logger = logger;
    this.depOptions = new DependencyOptions(config);

    initComponents();
  }

  @Override
  public void loadOptions() {
    tooltipCheckbox.setSelected(options.isEnableToolTips());
  }

  @Override
  public void applyOptions() {
    options.setEnableToolTips(tooltipCheckbox.isEnabled());
    depOptions.setAlgorithm((Class) algorithmComboBox.getSelectedItem());
    depOptions.setColoring((ColorOptions) coloringComboBox.getSelectedItem());
    depOptions.setShowLabels(labelSpinnerModel.getNumber().intValue());
  }

  private void initComponents() {
    JPanel optionsPanel = new JPanel();

    tooltipCheckbox.setText("Yes");

    Class<?>[] algorithms = { DistanceVertexContainer.class,
                              OutdegreeVertexContainer.class };

    algorithmComboBox.setModel(new DefaultComboBoxModel(algorithms));
    algorithmComboBox.setSelectedItem(DistanceVertexContainer.class);
    algorithmComboBox.setRenderer(new ClassCellRenderer());

    coloringComboBox.setModel(new DefaultComboBoxModel(ColorProvider.getInstance().getColorOptions()));
    coloringComboBox.setSelectedItem(ColorProvider.getInstance().getDefaultColorOption());

    int labelValue = depOptions.getShowLabels();
    labelSpinnerModel = new SpinnerNumberModel(labelValue, 0, 999, 1);

    JSpinner autoShowLabelBox = new JSpinner(labelSpinnerModel);

    optionsPanel.setLayout(new GridBagLayout());
    addOptionControls(optionsPanel, "Show tooltips?", tooltipCheckbox);
    addOptionControls(optionsPanel, "Measure:", algorithmComboBox);
    addOptionControls(optionsPanel, "Coloring scheme:", coloringComboBox);
    addOptionControls(optionsPanel, "Automatically shown number of labels:", autoShowLabelBox);

    JPanel controlPanel = new JPanel();
    controlPanel.add(startAnalysisButton);

    startAnalysisButton.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        workerManager.addAndRunTask(new DependencyCalculator(logger, options.getGraph(), depOptions),
            "Dependency Analysis");
      }
    });

    setLayout(new BorderLayout());
    add(optionsPanel, BorderLayout.NORTH);
    add(controlPanel, BorderLayout.SOUTH);

    ChangeListener applyOnChange = new ChangeListener() {
      @Override
      public void stateChanged(ChangeEvent event) {
        applyOptions();
      }
    };

    ActionListener applyOnAction = new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent event) {
        applyOptions();
      }
    };

    tooltipCheckbox.addChangeListener(applyOnChange);
    algorithmComboBox.addActionListener(applyOnAction);
    coloringComboBox.addActionListener(applyOnAction);
    autoShowLabelBox.addChangeListener(applyOnChange);
  }
}
